package com.gw.filter;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.cloud.commons.lang.StringUtils;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Component
public class AuthFilter implements GlobalFilter, Ordered {
    @Resource
    private RedisTemplate<String,String> redisTemplate;

    //
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 1. 所有访问网关的请求  请求头里面携带的有token
        ServerHttpRequest request = exchange.getRequest();
        String token = request.getHeaders().getFirst("Authorization");
        System.out.println("==================" + token);
        // 没有token  放行
        if (StringUtils.isBlank(token)) {
            //
            return chain.filter(exchange);

        } else {
            // 有token
            // 1 查看redis 里面有没有对应的key  有   放行
            String o =  redisTemplate.opsForValue().get(token);
            if(StringUtils.isNotBlank(o)){
                // 放行
                // 携带着token走  获取对应的token的值
                request.mutate().header("Authorization",o).build();

            }else{
                // 没有  refresh_
                String s = redisTemplate.opsForValue().get("refresh_" + token);
                // 刷新的token的值  不为空  => token的值过期
                if(StringUtils.isNotBlank(s)){
                    // bear123456
                    // 使用s的值  作为Authorization的值  访问资源
                    //
                    // 认证服务器  2. 发出一个post请求  获取生成token
                    // 设置请求参数
                    Map<Object, Object> entries = redisTemplate.opsForHash().entries(token + "_user");
                    System.out.println(entries);
                    Object username = entries.get("username");
                    Object password = entries.get("password");
                    Object loginType = entries.get("loginType");
                    HttpRequest params = HttpUtil.createPost("localhost:8500/oauth/token");
                    params.form("username",username);
                    params.form("password",password);
                    params.form("grant_type", "password");
                    params.form("client_id", "admin");
                    params.form("client_secret", "123456");
                    params.form("loginType", loginType);
                    //

                    HttpResponse response1 = params.execute(); // 执行
                    // code   body
                    String result = response1.body();
                    System.out.println("body:"+result);
                    JSONObject jsonObject = JSONObject.parseObject(result);   //string是要转化的json字符串     JSONObject为fastjson包里面
                    String body = jsonObject.getString("access_token");
                    String refreshToken = jsonObject.getString("refresh_token");
                    // 替换redis 原有的token的值
                    redisTemplate.expire(token+"_user",60*2,TimeUnit.MINUTES);
                    redisTemplate.opsForValue().set(token,"bearer"+body,60, TimeUnit.MINUTES);
                    redisTemplate.opsForValue().set("refresh_"+token,"bearer"+refreshToken,60*2, TimeUnit.MINUTES);
                   request.mutate().header("Authorization","bearer"+body).build();
                   //  token 续期
                    //  token :s
                    //
                }
            }

            return chain.filter(exchange);
        }

    }
    @Override
    public int getOrder() {
        return -1;
    }
}
